# -*- coding: utf-8 -*-
"""
通过对有标签数据集进行bootstrap采样初始化3个分类器
每个分类器更新用的无标签数据的标签由投票决定
三个分类器更新用的数据集相同
"""
from utils.SemiSupervisedClassifier import SemiSupervisedClassifier
from utils import load_txt_regex
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import numpy as np


class SelfTrainingClassifier2(SemiSupervisedClassifier):

    def __init__(self, base_estimator, unlabeled_data, unlabeled_label, cycles=10, random_state=None):
        super().__init__(base_estimator, unlabeled_data, unlabeled_label, random_state)
        self.cycles = cycles

    def _update_estimator(self, X, y):
        for i in range(self.cycles):
            self.train_scores.append(self.score(self.unlabeled_data, self.unlabeled_label))
            predictions = self.predict(self.unlabeled_data)
            h_X, h_y = self._bootstrap_sampling(self.unlabeled_data, predictions)
            # h_X, _, h_y, _ = train_test_split(self.unlabeled_data, predictions)
            # h_X = self.unlabeled_data
            # h_y = predictions
            h_X = np.concatenate((X, h_X), axis=0)
            h_y = np.concatenate((y, h_y), axis=0)
            for j in range(self.n_estimator):
                self.estimators_[j].fit(h_X, h_y)


if __name__ == '__main__':
    # 读取数据集
    path = r'../data/breast-cancer.data/breast-cancer_%s_%s_%s.asc'
    train_data = load_txt_regex(path % ('train', 'data', 1))
    train_label = load_txt_regex(path % ('train', 'labels', 1)).flatten()
    labeled_data, unlabeled_data, labeled_label, unlabeled_label = \
        train_test_split(train_data, train_label, test_size=0.8, random_state=919)
    test_data = load_txt_regex(path % ('test', 'data', 1))
    test_label = load_txt_regex(path % ('test', 'labels', 1)).flatten()
    # test_data = np.concatenate((test_data, load_txt_regex(path % ('test', 'data', 2))), axis=0)
    # test_label = np.concatenate((load_txt_regex(path % ('test', 'labels', 1)),
    #                              load_txt_regex(path % ('test', 'labels', 2))), axis=0).flatten()

    estimator = SVC()
    estimator.fit(train_data, train_label)
    estimator_ar = estimator.score(test_data, test_label)
    print("单个分类器在整个标签数据上准确率为%s" % estimator_ar)
    estimator.fit(labeled_data, labeled_label)
    estimator_ar = estimator.score(test_data, test_label)
    print("单个分类器在部分标签数据上准确率为%s" % estimator_ar)

    # cycles = 100
    # tri_ars = []
    # for i in range(cycles):
    #     try:
    #         print("run %s times" % i)
    #         tri = SimpleCoTrainingClassifier(estimator, unlabeled_data)
    #         tri.fit(labeled_data, labeled_label)
    #         tri_ar = tri.score(test_data, test_label)
    #         tri_ars.append(tri_ar)
    #     except ValueError as e:
    #         i -= 1
    #         continue
    # print("Co-Training在部分标签数据上运行%s次最大，最小，平均准确率为%s %s %s"
    #       % (cycles, np.max(tri_ars), np.min(tri_ars), np.average(tri_ars)))

    co = SelfTrainingClassifier2(estimator, unlabeled_data, unlabeled_label)
    co.fit(labeled_data, labeled_label)
    prediction = co.predict(test_data)
    print(co.score(test_data, test_label))
    print(co.train_scores[-1]-co.train_scores[0])
    print(co.train_scores)
